package com.gframework.mybatis.dao;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.reflection.MetaClass;
import org.apache.ibatis.reflection.ReflectionException;

import com.gframework.mybatis.config.MybatisConfig;
import com.gframework.util.GStringUtils;
import com.gframework.util.GUtils;

/**
 * 基于mybatis的将查询结果转换为特定类型的对象操作工具类.
 * 
 * @since 1.0.0
 * @author Ghwolf
 *
 */
final class SearchByTypeUtil {
	private SearchByTypeUtil(){}
	
	/**
	 * 将指定的map list集合转换为指定bean的对象集合.
	 */
	@SuppressWarnings("unchecked")
	static <R> List<R> list(List<Map<String,Object>> list,Class<R> type) {
		if (Map.class.isAssignableFrom(type)) return (List<R>) list ;
		if (list.isEmpty()) return Collections.emptyList();
		
		List<R> rList = new ArrayList<>(list.size());
		final MetaClass m = MybatisConfig.getMetaClass(type);
		final Object[] invokeParam = new Object[1];
		final Map<String,String> fieldNames = new HashMap<>();
		try {
			for (Map<String,Object> map : list) {
				R r = type.newInstance();
				for (Map.Entry<String, Object> entry : map.entrySet()) {
					String name = fieldNames.computeIfAbsent(entry.getKey(), GStringUtils :: toCamelCase);
					invokeParam[0] = GUtils.simpleTypeConversion(entry.getValue(), m.getSetterType(name));
					m.getSetInvoker(name).invoke(r,invokeParam);
				}
				rList.add(r);
			}
		} catch(IllegalAccessException | InstantiationException | InvocationTargetException e) {
			throw new ReflectionException(e);
		}
		return rList ;
	}

}
